package org.example;

import cn.hutool.core.io.resource.ResourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.example.entity.Field;
import org.example.entity.Table;
import org.example.util.ExcelUtil;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * apache poi 处理合并单元格简单例子
 */
@Slf4j
public class Demo02 {
    public static void main(String[] args) {
        try {
            //读取resource目录下文件
            InputStream stream = ResourceUtil.getStream("demo02.xlsx");
            //创建工作簿对象
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(stream);
            //获取工作簿下sheet的个数
            int sheetNum = xssfWorkbook.getNumberOfSheets();
            // 遍历每一个表格
            for (int i = 0; i < sheetNum; i++) {
                //存储字段数据
                List<Field> fields = new ArrayList<Field>();
                //存储表数据
                List<Table> tables = new ArrayList<Table>();
                Table table = new Table();
                //记录走过了几个合并的行数
                int mNum = 0;

                // 获取第i个表格
                XSSFSheet sheet = xssfWorkbook.getSheetAt(i);
                // 获取当前表格的最大行数,从零开始计算
                int maxRow = sheet.getLastRowNum();
                // 遍历当前表格的每一行,从第一行开始，因为第0行是表头
                for (int row = 1; row <= maxRow; row++) {
                    //每一行，包含一个字段信息，因此没一行循环初始化一个字段实体类
                    Field field = new Field();
                    //走过合并的行数+1
                    mNum++;
                    //获取融合行数,我的excel表格都是在第0列合并单元格，因此column为0。实际情况根据表格样式进行设置。
                    int mergedRowNum = ExcelUtil.getMergedRowNum(sheet, row, 0);
                    //该行的最大列数
                    int maxCellNum = sheet.getRow(row).getLastCellNum();
                    //遍历每一列,从1开始计算
                    for (int cellNum = 0; cellNum < maxCellNum; cellNum++) {
                        //判断该单元格是否是合并单元格
                        boolean isMerge = ExcelUtil.isMergedRegion(sheet, row, cellNum);
                        //获取row,cellNum单元格信息
                        XSSFCell cell = sheet.getRow(row).getCell(cellNum);

                        //是合并单元格，则为表信息，否则为字段信息
                        if (isMerge) {
                            //表名
                            String tableName = ExcelUtil.getMergedRegionValue(sheet,row,cellNum);
                            table.setName(tableName);
                            continue;
                        }

                        //获取单元格值
                        String value = ExcelUtil.getCellValue(cell);
                        //反馈
                        if (value == null) {//为空一般打印日志，或者反馈给前端作为提示。
                            log.info("第{} 行 第{} 列的值为空", row, cellNum);
                            continue;
                        }

                        //字段名
                        if (cellNum == 1) {
                            field.setName(value);
                        }
                        //字段类型
                        if (cellNum == 2) {
                            field.setType(value);
                        }
                        //字段中文名
                        if (cellNum == 3) {
                            field.setComment(value);
                        }
                    }
                    //循环完一个字段，添加到列表
                    fields.add(field);

                    //如果到达临界点，即开启下一个合并单元格前,初始化数据
                    if (mNum>=mergedRowNum){
                        //存储值
                        table.setFields(fields);
                        tables.add(table);
                        //初始化
                        mNum=0;
                        fields=new ArrayList<Field>();
                        table=new Table();
                    }

                }
                //输出表信息
                for (Table t : tables) {
                    System.out.println(t.getName());
                    System.out.println(t.getFields());
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
